C语言实现MD5算法 您所在的位置:网站首页 ios md5加密 C语言实现MD5算法

C语言实现MD5算法

#C语言实现MD5算法| 来源: 网络整理| 查看: 265

算法描述:

http://blog.sina.com.cn/s/blog_6fe0eb1901014cpl.html

步骤1:

我们是对一个字符串进行MD5加密,所以我们先从字符串的处理开始。首先我们要知道一个字符的长度是8位(bit),即一个字节的长度。现在我们要做的就是将一个字符串Str1分割成每512位为一个分组,形如N*512+R,最后多出来的不足512位的R部分先填充一个1,再接无数个0,直到补足512位。这里要注意,R为0时也要补位,这时候补512位,最高位1,形如1000…00;如果R超出448,除了要补满这个分组外,还要再补上一个512位的分组(因为超过448位则不能留64位出来存放字符串的原长)。 接着,讲讲将字符串分块保存部分。一个512位的字符串分组要分成16个32位的子分组,在每个32位中,以字节为单位通过小端规则存入一个32位的变量中,可以考虑用int类型的变量(一个int变量32位),也可以考虑用unsigned int,这样之后涉及的循环移位就不用考虑符号位了,这里还是以int为例。因为一个字符就是一个字节(8位),所以一个int类型变量能存放4个字符,假设一个字符串abcd,那么存在一个int类型变量中就是cdab。因此这里我们将字符串每4个字符分成一块,每一个块都以小端规则存放在一个int类型的变量中。估计有的人不清楚小端规则(Little-Endian),可以上网查,这里就不详细说了,见谅~ 补充好后的Str2长度为(N+1)*512位(如果R超出448,则是(N+2)*512),此时最低的64位预留,用来存放之前str1的长度length(长度为字符个数*8 bit)的值,如果这个length值的二进制位数大于64位,则只保留最低的64位。将这个64位的length放入之前填充好的str2的最后64位又要注意了:将length的64位分成4个16位,相当于4位2^16进制的数,再对这个数用小端规则排列,分别填入预留的64位。之前我就是这点没有领悟,估计大家也不是很懂,我举个例子:假设64位分成ABCD(A,B,C,D分别表示16位的二进制数,A是高位,D是低位),按小端规则排列后就是CDAB,将形如CDAB的64位按C(高位)到B(低位)的顺序填入str2预留的64位。 至此,补位的思想已经讲完了,这里再讲讲我的具体实现。我的思路是用一个长度为16的int类型的数组int M[16]。因为一个int类型数据有32位,16个加起来刚好一共512位,是一个分组的长度。我刚好就按顺序M[0]…M[15]表示一个512位的数。我再声明一个容器vector,用来存放每个M[16],因为分组个数不一定只有一个。 最后我举个例子方便大家理解。首先介绍一些常识:a – 61, b – 62, c – 63, d – 64, e – 65。这里“a – 61”表示a的ASCII码十六进制表示是0x61,其他以此类推。 好,假设一个字符串abcde,一共5个字符,长度length 为 5* 8 = 40 = 0x28。512位转化成十六进制就是64位。原字符串十六进制表示:61 62 63 64 65 00 00…00。完成补位后共512位,只有1个分组,形如: 61 62 63 64 65 80 00… 00(“80”的二进制是1000 0000,即之前的先补一个1,再补很多0的做法)。一个int M[16]的数组就够存了,即 M[0] = 64 63 62 61, M[1] = 00 00 80 65, M[2] = 0, M[3] = 0 … M[14] = 00 00 00 28, M[15] = 0   M[0]~M[15]设好之后,在内存中就是这样存的61 62 63 64 65 80 00…00(注意这里我们用MD5处理字符串时都考虑内存中的数据的排列顺序,得出的MD5也是需要按内存中的数据输出,所以经常要用小端规则转换) 看完这个例子,大家应该对步骤1的内容有比较全面的了解了  步骤2:

MD5有四个32位的被称作链接变量的整数参数,我们进行如下设置:                             A=0x67452301, B=0xefcdab89, C=0x98badcfe, D=0x10325476。 数据这样设置之后,存在内存中就按小端规则排列:01 23 45 67 89 ab cd ef …32 10 再声明四个中间变量a,b,c,d,赋值:a = A, b = B, c = C, d = D。 接着再设置四个非线性函数:                                     F(X,Y,Z) =(X&Y)|((~X)&Z)                                     G(X,Y,Z) =(X&Z)|(Y&(~Z))                                 H(X,Y,Z) =X^Y^Z       I(X,Y,Z)=Y^(X|(~Z)) (&是与,|是或,~是非,^是异或) 这四个函数的说明:如果X、Y和Z的对应位是独立和均匀的,那么结果的每一位也应是独立和均匀的。 假设M[j]表示消息的第j个子分组(从0到15),i[0] + ((UINT4) inLen i[0]) mdContext->i[1]++; mdContext->i[0] += ((UINT4) inLen i[1] += ((UINT4) inLen >> 29); while (inLen--) { /* add new character to buffer, increment mdi */ mdContext->in[mdi++] = *inBuf++; /* transform if necessary */ if (mdi == 0x40) { for (i = 0, ii = 0; i < 16; i++, ii += 4) in[i] = (((UINT4) mdContext->in[ii + 3]) in[ii + 2]) in[ii + 1]) in[ii]); Transform(mdContext->buf, in); mdi = 0; } } } void MD5Final(MD5_CTX *mdContext) { UINT4 in[16]; int mdi; unsigned int i, ii; unsigned int padLen; /* save number of bits */ in[14] = mdContext->i[0]; in[15] = mdContext->i[1]; /* compute number of bytes mod 64 */ mdi = (int) ((mdContext->i[0] >> 3) & 0x3F); /* pad out to 56 mod 64 */ padLen = (mdi < 56) ? (56 - mdi) : (120 - mdi); MD5Update(mdContext, PADDING, padLen); /* append length in bits and transform */ for (i = 0, ii = 0; i < 14; i++, ii += 4) in[i] = (((UINT4) mdContext->in[ii + 3]) in[ii + 2]) in[ii + 1]) in[ii]); Transform(mdContext->buf, in); /* store buffer in digest */ for (i = 0, ii = 0; i < 4; i++, ii += 4) { mdContext->digest[ii] = (unsigned char) (mdContext->buf[i] & 0xFF); mdContext->digest[ii + 1] = (unsigned char) ((mdContext->buf[i] >> 8) & 0xFF); mdContext->digest[ii + 2] = (unsigned char) ((mdContext->buf[i] >> 16) & 0xFF); mdContext->digest[ii + 3] = (unsigned char) ((mdContext->buf[i] >> 24) & 0xFF); } } /* Basic MD5 step. Transform buf based on in. */ static void Transform (unsigned long int *buf, unsigned long int *in) { unsigned long int a = buf[0], b = buf[1], c = buf[2], d = buf[3]; /* Round 1 */ #define S11 7 #define S12 12 #define S13 17 #define S14 22 FF(a, b, c, d, in[0], S11, 3614090360); /* 1 */ FF(d, a, b, c, in[1], S12, 3905402710); /* 2 */ FF(c, d, a, b, in[2], S13, 606105819); /* 3 */ FF(b, c, d, a, in[3], S14, 3250441966); /* 4 */ FF(a, b, c, d, in[4], S11, 4118548399); /* 5 */ FF(d, a, b, c, in[5], S12, 1200080426); /* 6 */ FF(c, d, a, b, in[6], S13, 2821735955); /* 7 */ FF(b, c, d, a, in[7], S14, 4249261313); /* 8 */ FF(a, b, c, d, in[8], S11, 1770035416); /* 9 */ FF(d, a, b, c, in[9], S12, 2336552879); /* 10 */ FF(c, d, a, b, in[10], S13, 4294925233); /* 11 */ FF(b, c, d, a, in[11], S14, 2304563134); /* 12 */ FF(a, b, c, d, in[12], S11, 1804603682); /* 13 */ FF(d, a, b, c, in[13], S12, 4254626195); /* 14 */ FF(c, d, a, b, in[14], S13, 2792965006); /* 15 */ FF(b, c, d, a, in[15], S14, 1236535329); /* 16 */ /* Round 2 */ #define S21 5 #define S22 9 #define S23 14 #define S24 20 GG(a, b, c, d, in[1], S21, 4129170786); /* 17 */ GG(d, a, b, c, in[6], S22, 3225465664); /* 18 */ GG(c, d, a, b, in[11], S23, 643717713); /* 19 */ GG(b, c, d, a, in[0], S24, 3921069994); /* 20 */ GG(a, b, c, d, in[5], S21, 3593408605); /* 21 */ GG(d, a, b, c, in[10], S22, 38016083); /* 22 */ GG(c, d, a, b, in[15], S23, 3634488961); /* 23 */ GG(b, c, d, a, in[4], S24, 3889429448); /* 24 */ GG(a, b, c, d, in[9], S21, 568446438); /* 25 */ GG(d, a, b, c, in[14], S22, 3275163606); /* 26 */ GG(c, d, a, b, in[3], S23, 4107603335); /* 27 */ GG(b, c, d, a, in[8], S24, 1163531501); /* 28 */ GG(a, b, c, d, in[13], S21, 2850285829); /* 29 */ GG(d, a, b, c, in[2], S22, 4243563512); /* 30 */ GG(c, d, a, b, in[7], S23, 1735328473); /* 31 */ GG(b, c, d, a, in[12], S24, 2368359562); /* 32 */ /* Round 3 */ #define S31 4 #define S32 11 #define S33 16 #define S34 23 HH(a, b, c, d, in[5], S31, 4294588738); /* 33 */ HH(d, a, b, c, in[8], S32, 2272392833); /* 34 */ HH(c, d, a, b, in[11], S33, 1839030562); /* 35 */ HH(b, c, d, a, in[14], S34, 4259657740); /* 36 */ HH(a, b, c, d, in[1], S31, 2763975236); /* 37 */ HH(d, a, b, c, in[4], S32, 1272893353); /* 38 */ HH(c, d, a, b, in[7], S33, 4139469664); /* 39 */ HH(b, c, d, a, in[10], S34, 3200236656); /* 40 */ HH(a, b, c, d, in[13], S31, 681279174); /* 41 */ HH(d, a, b, c, in[0], S32, 3936430074); /* 42 */ HH(c, d, a, b, in[3], S33, 3572445317); /* 43 */ HH(b, c, d, a, in[6], S34, 76029189); /* 44 */ HH(a, b, c, d, in[9], S31, 3654602809); /* 45 */ HH(d, a, b, c, in[12], S32, 3873151461); /* 46 */ HH(c, d, a, b, in[15], S33, 530742520); /* 47 */ HH(b, c, d, a, in[2], S34, 3299628645); /* 48 */ /* Round 4 */ #define S41 6 #define S42 10 #define S43 15 #define S44 21 II(a, b, c, d, in[0], S41, 4096336452); /* 49 */ II(d, a, b, c, in[7], S42, 1126891415); /* 50 */ II(c, d, a, b, in[14], S43, 2878612391); /* 51 */ II(b, c, d, a, in[5], S44, 4237533241); /* 52 */ II(a, b, c, d, in[12], S41, 1700485571); /* 53 */ II(d, a, b, c, in[3], S42, 2399980690); /* 54 */ II(c, d, a, b, in[10], S43, 4293915773); /* 55 */ II(b, c, d, a, in[1], S44, 2240044497); /* 56 */ II(a, b, c, d, in[8], S41, 1873313359); /* 57 */ II(d, a, b, c, in[15], S42, 4264355552); /* 58 */ II(c, d, a, b, in[6], S43, 2734768916); /* 59 */ II(b, c, d, a, in[13], S44, 1309151649); /* 60 */ II(a, b, c, d, in[4], S41, 4149444226); /* 61 */ II(d, a, b, c, in[11], S42, 3174756917); /* 62 */ II(c, d, a, b, in[2], S43, 718787259); /* 63 */ II(b, c, d, a, in[9], S44, 3951481745); /* 64 */ buf[0] += a; buf[1] += b; buf[2] += c; buf[3] += d; } /* ********************************************************************** ** End of md5.c ** ******************************* (cut) ******************************** */

md5driver.c:

/* ********************************************************************** ** md5driver.c -- sample routines to test ** ** RSA Data Security, Inc. MD5 message digest algorithm. ** ** Created: 2/16/90 RLR ** ** Updated: 1/91 SRD ** ********************************************************************** */ /* ********************************************************************** ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. ** ** ** ** RSA Data Security, Inc. makes no representations concerning ** ** either the merchantability of this software or the suitability ** ** of this software for any particular purpose. It is provided "as ** ** is" without express or implied warranty of any kind. ** ** ** ** These notices must be retained in any copies of any part of this ** ** documentation and/or software. ** ********************************************************************** */ #include #include #include #include /* -- include the following file if the file md5.h is separate -- */ #include "md5.h" /* Prints message digest buffer in mdContext as 32 hexadecimal digits. Order is from low-order byte to high-order byte of digest. Each byte is printed with high-order hexadecimal digit first. */ static void MDPrint(MD5_CTX *mdContext) { int i; for (i = 0; i < 16; i++) printf("%02x", mdContext->digest[i]); } /* size of test block */ #define TEST_BLOCK_SIZE 1000 /* number of blocks to process */ #define TEST_BLOCKS 10000 /* number of test bytes = TEST_BLOCK_SIZE * TEST_BLOCKS */ static long TEST_BYTES = (long) TEST_BLOCK_SIZE * (long) TEST_BLOCKS; /* A time trial routine, to measure the speed of MD5. Measures wall time required to digest TEST_BLOCKS * TEST_BLOCK_SIZE characters. */ static void MDTimeTrial() { MD5_CTX mdContext; time_t endTime, startTime; unsigned char data[TEST_BLOCK_SIZE]; unsigned int i; /* initialize test data */ for (i = 0; i < TEST_BLOCK_SIZE; i++) data[i] = (unsigned char) (i & 0xFF); /* start timer */ printf("MD5 time trial. Processing %ld characters...\n", TEST_BYTES); time(&startTime); /* digest data in TEST_BLOCK_SIZE byte blocks */ MD5Init(&mdContext); for (i = TEST_BLOCKS; i > 0; i--) MD5Update(&mdContext, data, TEST_BLOCK_SIZE); MD5Final(&mdContext); /* stop timer, get time difference */ time(&endTime); MDPrint(&mdContext); printf(" is digest of test input.\n"); printf("Seconds to process test input: %ld\n", (long) (endTime - startTime)); printf("Characters processed per second: %ld\n", TEST_BYTES / (endTime - startTime)); } /* Computes the message digest for string inString. Prints out message digest, a space, the string (in quotes) and a carriage return. */ static void MDString(char *inString) { MD5_CTX mdContext; unsigned int len = strlen(inString); MD5Init(&mdContext); MD5Update(&mdContext, inString, len); MD5Final(&mdContext); MDPrint(&mdContext); printf(" \"%s\"\n\n", inString); } /* Computes the message digest for a specified file. Prints out message digest, a space, the file name, and a carriage return. */ static void MDFile(char *filename) { FILE *inFile = fopen(filename, "rb"); MD5_CTX mdContext; int bytes; char data[1024]; if (inFile == NULL) { printf("%s can't be opened.\n", filename); return; } MD5Init(&mdContext); while ((bytes = fread(data, 1, 1024, inFile)) != 0) MD5Update(&mdContext, data, bytes); MD5Final(&mdContext); MDPrint(&mdContext); printf(" %s\n", filename); fclose(inFile); } /* Writes the message digest of the data from stdin onto stdout, followed by a carriage return. */ static void MDFilter() { MD5_CTX mdContext; int bytes; char data[16]; MD5Init(&mdContext); while ((bytes = fread(data, 1, 16, stdin)) != 0) MD5Update(&mdContext, data, bytes); MD5Final(&mdContext); MDPrint(&mdContext); printf("\n"); } /* Runs a standard suite of test data. */ static void MDTestSuite() { printf("MD5 test suite results:\n\n"); MDString(""); MDString("a"); MDString("abc"); MDString("message digest"); MDString("abcdefghijklmnopqrstuvwxyz"); MDString("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"); MDString("1234567890123456789012345678901234567890\ 1234567890123456789012345678901234567890"); /* Contents of file foo are "abc" */ MDFile("foo"); } void main(int argc, char *argv[]) { int i; /* For each command line argument in turn: ** filename -- prints message digest and name of file ** -sstring -- prints message digest and contents of string ** -t -- prints time trial statistics for 1M characters ** -x -- execute a standard suite of test data ** (no args) -- writes messages digest of stdin onto stdout */ if (argc == 1) { MDFilter(); } else { for (i = 1; i < argc; i++) { if (argv[i][0] == '-' && argv[i][1] == 's') { MDString(argv[i] + 2); } else if (strcmp(argv[i], "-t") == 0) { MDTimeTrial(); } else if (strcmp(argv[i], "-x") == 0) { MDTestSuite(); } else { MDFile(argv[i]); } } } } /* ********************************************************************** ** End of md5driver.c ** ******************************* (cut) ******************************** */

在VS2010中新建控制台空项目,加入上述代码,设置命令行参数为-x,就会显示测试结果。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有